package com.hb.trade.server.center.au.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hb.core.pojo.center.au.dto.RoleDTO;
import com.hb.core.pojo.center.au.dto.UserDTO;
import com.hb.core.pojo.center.au.entity.Org;
import com.hb.core.pojo.center.au.entity.Role;
import com.hb.core.pojo.center.au.entity.User;
import com.hb.core.pojo.enums.RoleTypeEnum;
import com.hb.core.pojo.parent.MPBaseController;
import com.hb.core.pojo.parent.PageResult;
import com.hb.trade.server.center.au.manager.UserManager;
import com.hb.trade.server.center.au.service.*;
import org.fzzn.core.model.enums.MsgEnum;
import org.fzzn.core.model.msg.Message;
import org.fzzn.core.util.Enums;
import org.fzzn.core.util.MsgUtil;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * 角色信息表 前端控制器
 *
 * @author zhaojk
 * @since 2021-11-29
 */
@RestController
public class RoleController extends MPBaseController<Role, RoleService> {

    protected final OrgService orgService;
    protected final UserService userService;
    protected final UserRoleService userRoleService;
    protected final RoleResourceService roleResourceService;

    public RoleController(RoleService service,
                          OrgService orgService,
                          UserService userService,
                          UserRoleService userRoleService,
                          RoleResourceService roleResourceService) {
        super(service);
        this.orgService = orgService;
        this.userService = userService;
        this.userRoleService = userRoleService;
        this.roleResourceService = roleResourceService;
    }

    /**
     * 角色列表
     * 角色查询增加roleSign条件的过滤
     *
     * @return
     */
    @PostMapping("/role/listRoles")
    public Message<List<Role>> listRoles(@RequestBody RoleDTO roleDTO) {
        // 查询指定企业下的角色列表
        Long orgId = roleDTO.getOrgId();
        QueryWrapper<Role> wrapper = Role.wrapper("id", "role_code", "role_name", "role_sign", "role_type");
        wrapper.eq("org_id", orgId)
                .eq(roleDTO.getRoleSign() != null, "role_sign", roleDTO.getRoleSign());
        List<Role> rootList = service.list(wrapper);

        // 只有总公司帐号会显示"分公司管理员"角色
        Integer accountLevel = roleDTO.getAccountLevel();
        if (accountLevel != null) {
            switch (accountLevel) {
                case 1: // 总公司帐号
                    // 如果该企业上面有总公司, 再去查询总公司下的分公司管理员角色
                    Org org = orgService.getById(orgId);
                    QueryWrapper<Role> wrapperBranchManager = Role.wrapper("id", "role_code", "role_name", "role_sign", "role_type");
                    wrapperBranchManager.eq("org_id", org.getParentId())
                            .eq(roleDTO.getRoleSign() != null, "role_sign", roleDTO.getRoleSign())
                            .eq("role_type", RoleTypeEnum.BRANCH_COMPANY_MANAGER.getCode());
                    List<Role> branchManagerList = service.list(wrapperBranchManager);
                    rootList.addAll(0, branchManagerList);
                    break;
                case 2: // 分公司帐号
                default:
                    break;
            }
        }


        return MsgUtil.success(rootList);
    }

    /**
     * 获取指定用户拥有的所有角色
     * 参数支持id和username
     *
     * @param userDTO#id
     * @param userDTO#username
     * @return
     */
    @PostMapping("/role/listRolesByUser")
    public Message<List<RoleDTO>> listRolesByUser(@RequestBody UserDTO userDTO) {
        // 用户验证
        Long userId = userDTO.getId();
        String username = userDTO.getUsername();
        if (userId == null && StrUtil.isEmpty(username)) {
            return MsgUtil.msg(MsgEnum.INCORRECT_PARAM);
        }

        // 查询用户的全部角色
        QueryWrapper<User> wrapper = UserDTO.wrapper();
        wrapper.eq("id", userId).or((innerWrapper) -> innerWrapper.eq("username", username))
                .last("limit 1");

        User user = userService.getOne(wrapper);
        UserManager userManager = user.to(UserManager.class);
        boolean admin = userManager.isAdmin();

        // 如果是超级管理员, 返回所有角色
        if (admin) {
            List<Role> list = service.list(Role.wrapper());
            List<RoleDTO> roleDTOS = CollUtil.map(list, (role) -> role.to(RoleDTO.class), true);
            return MsgUtil.success(roleDTOS);
        }

        // 其他用户返回查询列表
        Long orgUserId = user.getId();
        List<RoleDTO> roleDTOS = userRoleService.listRolesByUserId(orgUserId);
        return MsgUtil.msg(roleDTOS);
    }

    /**
     * 角色分页列表
     *
     * @return
     */
    @PostMapping("/role/pageRoles")
    public Message<PageResult<RoleDTO>> pageRoles(@RequestBody RoleDTO roleDTO) {
        Page<RoleDTO> rolePage = roleDTO.pages();
        service.pageRoles(rolePage, roleDTO);
        PageResult<RoleDTO> rolePageResult = PageResult.get(rolePage);
        return MsgUtil.success(rolePageResult);
    }

    /**
     * 角色分页列表, 后台管理用
     *
     * @return
     */
    @PostMapping("/role/pageManagementRoles")
    public Message<PageResult<RoleDTO>> pageManagementRoles(@RequestBody RoleDTO roleDTO) {
        Page<RoleDTO> rolePage = roleDTO.pages();
        service.pageManagementRoles(rolePage, roleDTO);
        PageResult<RoleDTO> rolePageResult = PageResult.get(rolePage);
        return MsgUtil.success(rolePageResult);
    }

    /**
     * 新增或更新角色信息
     *
     * @return
     */
    @PostMapping("/role/saveRole")
    public Message<Boolean> saveRole(@RequestBody RoleDTO roleDTO) {
        roleDTO.init();

        // 判断roleCode是否存在
        QueryWrapper<Role> wrapper = Role.wrapper();
        wrapper.eq("role_code", roleDTO.getRoleCode())
                .eq("org_id", roleDTO.getOrgId())
                .ne(roleDTO.getId() != null, "id", roleDTO.getId());
        long count = service.count(wrapper);
        if (count > 0) {
            return MsgUtil.fail("角色代码已经存在");
        }

        // 保存或更新角色信息
        Long roleId = roleDTO.getId();
        if (roleId == null) {
            // 新增操作
            roleDTO.buildBaseData(1);
            boolean save = service.save(roleDTO);

            // 更新权限信息
            updatePermissions(roleDTO);

            return MsgUtil.success(save);
        }

        // 更新操作
        Role orgRole = getById(roleId);
        orgRole = roleDTO.to(orgRole);
        orgRole.buildBaseData(2);
        boolean update = service.updateById(orgRole);

        // 更新权限信息
        updatePermissions(roleDTO);

        return MsgUtil.success(update);
    }

    /**
     * 删除角色
     *
     * @return
     */
    @PostMapping("/role/removeRole")
    public Message<Boolean> removeRole(@RequestBody RoleDTO roleDTO) {
        Long roleId = roleDTO.getId();
        if (roleId == null) {
            return MsgUtil.msg(MsgEnum.INCORRECT_PARAM);
        }

        Role role = service.getById(roleId);
        Integer roleType = role.getRoleType();
        RoleTypeEnum typeEnum = Enums.of(RoleTypeEnum.class, roleType);
        if (typeEnum != null) {
            return MsgUtil.fail("系统角色不允许删除");
        }

        // 删除角色信息
        boolean remove = service.removeById(roleId);

        // 删除角色菜单表中的关联数据
        roleResourceService.cleanRolePermissions(roleId);

        return MsgUtil.success(remove);
    }

    /**
     * 更新角色的权限
     *
     * @return
     */
    @PostMapping("/role/updatePermissions")
    public Message<Boolean> updatePermissions(@RequestBody RoleDTO roleDTO) {
        // 更新角色权限
        boolean result = roleResourceService.updatePermissionsWithMenuIds(roleDTO.getId(), roleDTO.getResIds());
        return MsgUtil.success(result);
    }

    /**
     * 查询指定角色下的用户成员列表
     *
     * @param roleDTO#id       角色ID
     * @param roleDTO#pageFlag 返回形式(1: 分页对象, 2: 列表对象)
     * @return
     */
    @PostMapping("/role/membersByRole")
    public Message<RoleDTO> membersByRole(@RequestBody RoleDTO roleDTO) {
        Long roleId = roleDTO.getId();
        if (roleId == null) {
            return MsgUtil.msg(MsgEnum.INCORRECT_PARAM);
        }
        Integer pageFlag = roleDTO.getPageFlag();
        if (pageFlag == null) {
            return MsgUtil.msg(MsgEnum.INCORRECT_PARAM);
        }

        Object users = userService.usersByRoleId(roleDTO);

        // 查询角色信息
        Role role = service.getById(roleId);
        if (role == null) {
            return MsgUtil.msg(MsgEnum.NULL_RESULT);
        }
        RoleDTO orgRoleDTO = role.to(RoleDTO.class);

        // 查询该角色下的用户成员
        orgRoleDTO.setUsers(users);
        return MsgUtil.success(orgRoleDTO);
    }

    /**
     * 查询用户或企业的业务角色列表
     *
     * @param orgOrUserId 企业ID或者用户ID
     * @return
     */
    @PostMapping("/role/listBiddingRoles")
    public Message<List<RoleDTO>> listBiddingRoles(Long orgOrUserId) {
        if (orgOrUserId == null) {
            return MsgUtil.msg(MsgEnum.INCORRECT_PARAM);
        }
        // 查询参数中对应的用户列表
        User user = userService.getById(orgOrUserId);
        List<User> userList = userService.listByOrgId(orgOrUserId);

        if (user != null) {
            userList.add(user);
        }

        // 啥也没有
        if (userList.size() == 0) {
            return MsgUtil.msg(MsgEnum.NULL_RESULT);
        }

        List<Long> userIds = CollUtil.map(userList, User::getId, true);

        // 查询该角色下的用户成员
        List<RoleDTO> roles = userRoleService.listBiddingRolesByUserIds(userIds);
        if (CollUtil.isEmpty(roles)) {
            return MsgUtil.msg(MsgEnum.NULL_RESULT);
        }
        return MsgUtil.success(roles);
    }

    /**
     * 角色详情(点击编辑时回显)
     *
     * @param roleDTO#id
     * @return
     */
    @PostMapping("/role/roleDetail")
    public Message<Role> roleDetail(@RequestBody RoleDTO roleDTO) {
        Role role = service.getById(roleDTO.getId());
        return MsgUtil.msg(role);
    }

    /**
     * 根据roleType查询角色
     *
     * @param roleType
     */
    @PostMapping("/role/getRoleByRoleType")
    public Message<Role> getRoleByRoleType(RoleTypeEnum roleType) {
        Role role = service.getRoleByRoleType(roleType);
        return MsgUtil.success(role);
    }
}
